package com.zjl.redis.第05章_redis的多环境部署;

import io.lettuce.core.cluster.SlotHash;
import io.lettuce.core.codec.CRC16;

/**
 * 工作方式： 16384 = 2^14  16383 = 0B0011111111111111  二进制的这个
 *     在redis的每一个节点上，都有这么两个东西，一个是 插槽（slot），
 *     它的的取值范围是：0-16383。还有一个就是 cluster，可以理解为是一个集群管理的插件。
 *     当我们的存取的key到达的时候，redis会根据 crc16 的算法得出一个结果，
 *     然后把结果对 16384 求余数，这样每个 key 都会对应一个编号在
 *     0-16383 之间的哈希槽，通过这个值，去找到对应的插槽所对应的节点，
 *     然后直接自动跳转到这个对应的节点上进行存取操作。
 *     *********** 这个插槽的范围是可以改变的，建议改成 1000左右 *************
 *
 * 集群  里的Redis都要启动  但是只要执行一个  集群会给你自动配置
 * 他的主服务器信息有个插槽  [0-16383]   多主服务器自动分配
 *   每个存储信息   会算出一个插槽值   （集群使用CRC16(key)）%16384  算出插槽值
 *   在某个插槽值范围内  存储在不同的主服务器中  他会切换到最近执行的主服务器
 *   比如 三个的话   [0-5460]   [5461-10922]    [10923-16383]
 *
 * （集群使用CRC16(key)）%16384
 * 你咋知道用的这个方法
 *      在解压文件中 的 src 目录下
 *      有个 clister.c 文件
 *      里的
 *      unsigned int keyHashSlot(char *key, int keylen)
 *      方法 中
 *      crc16(key,keylen) & 0x3FFF
 *      表明了用 CRC16 算法
 *      C还有个 crc16.c 文件 就是算法逻辑
 *
 * 由于 redis的槽位用了 CRC16 算法，CRC16算法有 65536 个值，
 * 为啥使用 16354 个槽位，不使用 65536 呢？
 *      因为 65538/8/1024 =8KB 个字节   占用字节数太大，浪费
 *      因为 16354/8/1024 =2KB 个字节
 *
 */
public class C3_槽位的解释 {
    public static void main(String[] args) {
        System.out.println(1<<14);
        int k1 = 0B0011111111111111;//16383
        int k2 = 0B0100000000000000;//16384
        System.out.println(k1);
        System.out.println(k2);
        System.out.println("-----------------");
        System.out.println(SlotHash.getSlot("B"));//判断此值的槽位数
        System.out.println(CRC16.crc16("B".getBytes()));//CRC16算法
        System.out.println(CRC16.crc16("B".getBytes())&16383);//

    }
}
